package widgets

import (
	"strings"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/data/binding"
	"fyne.io/fyne/v2/dialog"
	"fyne.io/fyne/v2/theme"
	"fyne.io/fyne/v2/widget"
	"github.com/gogf/gf/v2/container/garray"
	"github.com/gogf/gf/v2/container/gmap"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/util/gconv"
	octicons "github.com/lusingander/fyne-octicons"
	"github.com/y2h/fyne_poem/dbb"
	"github.com/y2h/fyne_poem/util"
)

var rsData gdb.Result

// 数据表格容器
var CtnData *fyne.Container

// 数据表格表头即列名容器
var CtnHeader *fyne.Container
var lstData *widget.List

// 数据表记录总数
var bdTotal binding.Int
var page util.Page

var pageSize = 10
var currentPage = 1

func setup() {
	bdTotal = binding.NewInt()
	lstData = widget.NewList(nil, nil, nil)
}
func TblData(db gdb.DB, tbl string,
	msg *widget.Label, w fyne.Window, a fyne.App) fyne.CanvasObject {
	if tbl == "" || db == nil {
		msg.SetText("please choose a table")
		return widget.NewLabel("no db or table")
	}
	setup()
	total, _ := db.Model(tbl).Count()
	bdTotal.Set(total)
	_, tblCols := dbb.SqliteTblColsGF(db, tbl)
	page = util.Paginator(currentPage, pageSize, int64(total))
	lblTotal := widget.NewLabel(gconv.String(currentPage) + "/" +
		gconv.String(page.Totalpages))
	bdTotal.AddListener(binding.NewDataListener(func() {
		page = util.Paginator(currentPage, pageSize, int64(total))
		lblTotal.SetText(gconv.String(currentPage) + "/" +
			gconv.String(page.Totalpages))
		rs, _ := db.Model(tbl).OrderDesc(tblCols[0]).Limit(20).All()
		RefreshListResult(lstData, db, tbl, rs, msg, w)
	}))

	lenCols := len(tblCols)
	rsData, _ = db.Model(tbl).OrderDesc(tblCols[0]).Limit(20).All()
	RefreshListResult(lstData, db, tbl, rsData, msg, w)
	selectId := 0
	lstData.OnSelected = func(id widget.ListItemID) {
		selectId = id
		msg.SetText(gconv.String(rsData[selectId].GMap().Get(tblCols[0])))
	}
	searchTxt := widget.NewEntry()
	searchTxt.SetPlaceHolder("please input search key word here, lsm,李世民")
	searchTxt.SetText("")
	sel := widget.NewSelect(tblCols, nil)
	btnSearch := widget.NewButtonWithIcon("", theme.SearchIcon(),
		func() {
			searchStr := strings.TrimSpace(searchTxt.Text)
			if searchStr == "" {
				searchTxt.SetText("please input the content you want to search")
				return
			}
			// result, _ := db.Model(tbl).WhereLike(sel.Selected,
			// 	"%"+searchTxt.Text+"%").All()

			m := db.Model(tbl)
			for i := 0; i < lenCols; i++ {
				m.WhereOrLike(tblCols[i], "%"+searchTxt.Text+"%")
			}
			result, _ := m.All()

			l := widget.NewList(func() int {
				return result.Len()
			}, func() fyne.CanvasObject {
				c := container.NewGridWithColumns(lenCols)
				for i := 0; i < lenCols; i++ {
					c.Add(widget.NewLabel("data"))
				}
				return c
			}, func(lii widget.ListItemID, co fyne.CanvasObject) {
				c := co.(*fyne.Container)
				for i := 0; i < lenCols; i++ {
					lbl := c.Objects[i].(*widget.Label)
					lbl.SetText(gconv.String(result[lii].GMap().Get(tblCols[i])))
				}
			})
			w := a.NewWindow("search data of " + tbl + "共搜索到 [" +
				gconv.String(result.Len()) + "] 条包含 [" + searchStr + "] 的数据")
			w.Resize(fyne.NewSize(800, 700))
			w.SetContent(l)
			w.Show()

		})
	searchTxt.OnSubmitted = func(s string) {
		btnSearch.OnTapped()
	}
	// 新增纪录
	btnInsert := widget.NewButtonWithIcon("", octicons.PlusIcon(),
		func() {
			frm := widget.NewForm()
			d := gmap.New()
			_, tblCols := dbb.SqliteTblColsGF(db, tbl)
			garray.NewStrArrayFrom(tblCols).Walk(func(value string) string {
				d.Set(value, widget.NewEntry())
				frm.Append(value, d.Get(value).(*widget.Entry))
				return value
			})
			frm.Append("", widget.NewButton("Submit", func() {
				dd := gmap.New()
				d.Iterator(func(k, v interface{}) bool {
					dd.Set(k, strings.TrimSpace(v.(*widget.Entry).Text))
					return true
				})
				_, err := db.Model(tbl).Insert(dd)

				if err != nil {
					msg.SetText("insert err " + err.Error())
					return
				}

				msg.SetText("insert success")
				total, _ := db.Model(tbl).Count()
				bdTotal.Set(total)
			}))

			msg.SetText("insert success")
			w := a.NewWindow("insert record")
			w.Resize(fyne.NewSize(800, 700))
			w.SetContent(frm)
			w.Show()
		})
	btnDelete := widget.NewButtonWithIcon("", theme.DeleteIcon(),
		func() {
			delID := gconv.String(rsData[selectId].GMap().Get(tblCols[0]))
			dialog.ShowConfirm("Delete data", "Are you sure to delete "+delID,
				func(b bool) {
					if selectId < 0 {
						msg.SetText("please select a record")
						return
					}
					if b {
						_, err := db.Model(tbl).Delete(tblCols[0], delID)
						if err != nil {
							msg.SetText(err.Error())
							return
						}
						msg.SetText("delete" + delID)
						total, _ := db.Model(tbl).Count()
						bdTotal.Set(total)
					} else {
						msg.SetText("cancel delete")
						return
					}
				}, w)
		})
	btnOutput := widget.NewButtonWithIcon("", theme.DocumentSaveIcon(),
		func() {

		})

	top := container.NewVBox(
		searchTxt,
		container.NewHBox(sel, btnSearch, btnInsert, btnDelete, btnOutput),
	)

	pagesHbox := container.NewHBox()
	for i := 0; i < 5; i++ {
		pagesHbox.Add(widget.NewButton("1", nil))
	}
	currPagebd := binding.BindInt(&currentPage)
	currPagebd.AddListener(binding.NewDataListener(func() {
		total, _ := db.Model(tbl).Count()
		page = util.Paginator(currentPage, pageSize, int64(total))

		garray.NewIntArrayFrom(page.Pages).Iterator(func(k, v int) bool {
			btn := pagesHbox.Objects[k].(*widget.Button)
			btn.SetText(gconv.String(v))
			btn.OnTapped = func() {
				currPagebd.Set(v)
			}
			return true
		})

		rs, _ := db.Model(tbl).OrderDesc(tblCols[0]).
			Limit(pageSize).Offset(pageSize * (currentPage - 1)).All()
		RefreshListResult(lstData, db, tbl, rs, msg, w)

		lblTotal.SetText(gconv.String(currentPage) + "/" +
			gconv.String(page.Totalpages))
	}))

	btnFirsDatat := widget.NewButton("FirstPage", func() {
		currPagebd.Set(1)
	})
	btnPrev := widget.NewButton("PrevPage", func() {
		if currentPage < 2 {
			msg.SetText("FirsDatat page")
			return
		}
		currPagebd.Set(currentPage - 1)
	})
	btnNext := widget.NewButton("NextPage", func() {
		if currentPage > page.Totalpages-1 {
			msg.SetText("Last page")
			return
		}
		currPagebd.Set(currentPage + 1)
	})
	btnLast := widget.NewButton("LastPage", func() {
		currPagebd.Set(page.Totalpages)
	})
	bottom := container.NewHBox(btnFirsDatat, btnPrev, pagesHbox, btnNext, btnLast, lblTotal)
	if total < pageSize {
		bottom.Hide()
	} else {
		bottom.Show()
	}
	CtnHeader = container.NewMax(Header(tblCols, 2))
	CtnData = container.NewBorder(CtnHeader, nil, nil, nil, lstData)
	cc := container.NewBorder(top, bottom, nil, nil,
		CtnData)

	return cc
}
